#pragma warning(disable:6031)//取消VS编译器的一个警告
#include "LinkList.h" //引用头文件

//初始化算法
int InitList(SL* L) {
	*L = (SL)malloc(sizeof(Stu_List));//分配空间
	if (!(*L)) {// 错误处理
		return ERROR;
	}
	(*L)->next = NULL;//初始化
	printf("成功初始化！\n");//反馈
	return 0;
}

//取值算法
int GetList(const SL L, const int i, Student* data) {
	if (i < 1) {//录入核验
		return ERROR;
	}
	SL p = L->next;//定义p指针并指向首元结点
	int j = 1;//定义j，记录已经走过的结点数
	for (j = 1;j < i && p != NULL;j++) { //当移动到指定结点或p为空时结束循环，用while也可以
		p = p->next;//移动p指针
	}
	if (j < i || !p) { //错误核验
		return ERROR;
	}
	*data = p->Data;//返回取的值，要用*
	return 0;
}

//按值查找算法
int Locate_Value(const SL L, const char* name) {
	if (L->next == NULL) return ERROR;//空值判断
	SL p = L->next;//定义p指针并指向首元结点
	int j = 1;//代表已经走过的结点数
	while (strcmp(p->Data.name,name) != 0 && p!= NULL) {//找到值，或走到最后结点，结束循环
		p = p->next;//向后移动p指针
		j++;//记录走过的节点数
	}
	if (p == NULL) {//错误判断
		return ERROR;
	}
	return j;
}

//按地址查找算法
int Locate_Address( const SL L,int i , char* name ){
	if (L->next == NULL) {//空值判断
		return ERROR;
	}
	SL p = L->next;//定义p指针并指向首元结点
	int j = 1;//代表已经走过的结点数
	while (j != i && p != NULL) {//找到地址，或走到尾元结点，结束循环
		p = p->next;//向后移动p指针
		j++;//记录走过的节点数
	}
	if (p == NULL) {//错误判断
		return ERROR;
	}
	strcpy(name,p->Data.name);//返回目的地数据
	return 0;
}

//数据插入算法
int Insert_List( SL L, int i, const Student insert) {
	if (i < 1) {//录入值判断
		return ERROR;
	}
	SL p = L;//定义p指向头结点
	int j = 0;//用来记录走过的结点数
	while (p != NULL && j < i-1) {//到地址或到尾元结点结束循环
		p = p->next;//p指针移动
		j++;//走过的节点数+1
	}
	if (p == NULL) {//错误判断
		return ERROR;
	}
	SL ins_list = (SL)malloc(sizeof(Stu_List));//为要插入的结点分配空间
	if (ins_list == NULL) {//分配失败处理
		return ERROR;
	}
	ins_list->Data = insert;//数据录入
	ins_list->next = p->next;//后续结点链接
	p->next = ins_list;//前结点链接，上下顺序不能错
	return 0;
}

//删除数据算法
int Del_List(SL L, int i, Student* del) {
	if (i < 1) {//录入值核验
		return ERROR;
	}
	SL p = L;//定义p并指向L
	int j = 0;//用来记录走过的结点数
	while (j < i - 1 && p != NULL) {//到达目的地或走到尾元结点结束循环
		p = p->next;//p向前移动
		j++;//走过的结点+1
	}
	if (p == NULL) {//错误判断
		return ERROR;
	}
	del->stu_no = p->next->Data.stu_no;//记录要被删除的结点数据
	strcpy(del->name, p->next->Data.name);
	strcpy(del->sex, p->next->Data.sex);
	SL q = p->next->next;//记录被删除结点的下一个结点
	free(p->next);//释放被删除的结点
	p->next = q;//要被删除的结点链接脱离，链接到下一个结点上
	return 0;
}

//清空链表算法
int Clean_List(SL L) {
	if (L->next == NULL) {//判断链表是否本身就是空的
		return 0;//本身就是空的不是错误，所以不用返回ERROR
	}
	SL p = L;//p指向L
	while (L->next != NULL) {//有结点没有被释放就继续循环
		p = p->next;//p指向首元结点
		L->next = p->next;//将第二结点转为首元结点
		free(p);//释放原首元结点
		p = L->next;//p指向新首元结点
	}
	return 0;
}

//前插法录入链表算法
int EnterList_H(SL L , int i) {
	if (i < 0) return ERROR;
	int j = 0;//用来计数比较
	SL enter_list = NULL;

	do {//循环录入节点数据
		enter_list = (SL)malloc(sizeof(Stu_List));//分配空间
		if (enter_list == NULL) {//空间分配失败处理
			break;
		}
		j++;//记录的学生个数+1
		enter_list->next = L->next;//首元素指针转接
		L->next = enter_list; //头指针转接，顺序不能错
		printf("请输入学生%d学号:",j);
		scanf("%d",&(enter_list->Data.stu_no));//录入信息
		printf("请输入学生%d姓名:", j);
		scanf("%s", &(enter_list->Data.name));
		printf("请输入学生%d性别:", j);
		scanf("%s", &(enter_list->Data.sex));
	} while (j < i);//判断是否够数，不够继续循环

	if (enter_list == NULL) {//判断是否出现空间分配失败现象
		printf("遇到错误，总共录入了%d名学生资料\n", j);//反馈
		return ERROR;
	}
	
	return 0;
}

//后插法录入链表算法
int EnterList_R(SL L, int i) {
	if (i < 0) {//录入核验
		return ERROR;
	}

	int j = 0;//用作记录已经录入的结点数量
	SL p = L;//p初始化指向L，后续用作锚点
	while (p->next != NULL) {//将p移动到尾元结点
		p = p->next;
	}
	SL enter_list = NULL;//定义一个指针，后续用来开辟新节点

	do {
		enter_list = (SL)malloc(sizeof(Stu_List));//分配空间
		if (enter_list == NULL) {//错误查验
			break;
		}
		j++;//记录的学生数+1
		enter_list->next = NULL;//初始化
		p->next = enter_list;//尾元结点链接
		p = p->next;//p指向新尾元结点
		printf("请输入学生%d学号:", j);//录入信息
		scanf("%d", &(enter_list->Data.stu_no));
		printf("请输入学生%d姓名:", j);
		scanf("%s", &(enter_list->Data.name));
		printf("请输入学生%d性别:", j);
		scanf("%s", &(enter_list->Data.sex));
	} while (j < i);//判断是否够数，不够继续循环

	if (enter_list == NULL) {//判断是否出现空间分配失败现象
		printf("遇到错误，总共录入了%d名学生资料\n", j);//反馈
		return ERROR;
	}

	return 0;
}
